package jmind.core.concurrent;

import java.util.Map;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import com.google.common.collect.Maps;

/**
 * 当调用读锁lock方法时，如果没有线程持有写锁，就可获得读锁。
 * 这也意味着只要进行读的时候没有其他线程在进行写的操作，读的操作就是无阻塞的。
 * 当调用写锁的lock方法时，如果此时没有线程持有读锁或写锁，则可继续执行，
 * 这也意味着要进行写动作时，如果有其他线程在读或者在写，就会被阻塞。因此写的性能有可能会下降。
 * @author wbxie
 * 2014年7月2日
 */
public class ReentrantReadWriteLockTest22222 {
    private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    private static Map<Integer, String> maps = Maps.newHashMap();
    static CountDownLatch latch = new CountDownLatch(102);
    private static CyclicBarrier barrier = new CyclicBarrier(102);

    public static void main(String[] args) {

        long beginTime = System.currentTimeMillis();
        for (int i = 0; i < 100; i++) {
            new Thread(new ReadThread()).start();
        }
        for (int i = 0; i < 2; i++) {
            new Thread(new WriteThread()).start();
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        long time = System.currentTimeMillis() - beginTime;
        System.out.println("Consume Time is: " + time);
    }

    static class ReadThread implements Runnable {

        @Override
        public void run() {
            try {
                barrier.await();

            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            lock.readLock().lock();
            maps.get(1);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            lock.readLock().unlock();
            latch.countDown();
        }

    }

    static class WriteThread implements Runnable {

        @Override
        public void run() {
            try {
                barrier.await();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                lock.writeLock().lock();
                maps.put(1, "wdsdsd");
                Thread.sleep(100);
            } catch (Exception e) {
                // TODO: handle exception
            } finally {
                lock.writeLock().unlock();
            }
            latch.countDown();

        }

    }

}
